﻿using System.Collections.Generic;
using System.IO;
using System.Globalization;
using System.Xml;

namespace PerformanceDude.MSBuildShellExtension
{
    public class MSBuildFile
    {
        private string fileName;

        public int Version { get; set; }

        public ICollection<MSBuildFileTarget> Targets { get; set; }

        private List<MSBuildFileTarget> DefaultTargets = new List<MSBuildFileTarget>()
        {
            new MSBuildFileTarget(){TargetName = "Build"},
            new MSBuildFileTarget(){TargetName = "Rebuild"},
            new MSBuildFileTarget(){TargetName = "Clean"}
        };

        public MSBuildFile(string fileName)
        {
            this.fileName = fileName;

            string extension = Path.GetExtension(fileName);

            #region sln
            if (extension == ".sln")
            {
                Solution sln = new Solution(fileName);

                switch (sln.Version)
                {
                    case 11:
                        this.Version = 2;
                        break;
                    case 10:
                        this.Version = 1;
                        break;
                    case 9:
                        this.Version = 0;
                        break;
                }

                this.Targets = new List<MSBuildFileTarget>(this.DefaultTargets); //will target default configuration and platform

                foreach (MSBuildFileTarget defaultTarget in this.DefaultTargets)
                {
                    foreach (SolutionConfiguration configuration in sln.SolutionConfigurations)
                    {
                        this.Targets.Add(
                            new MSBuildFileTarget()
                            {
                                TargetName = defaultTarget.TargetName,
                                ConfigurationName = configuration.ConfigurationName,
                                PlatformName = configuration.PlatformName
                            });
                    }
                }
            }
            #endregion

            #region *proj
            else if (new List<string>(){".csproj", ".vbproj" ,".vcxproj", ".vjsproj"}.Contains(extension))
            {
                XmlDocument file = new XmlDocument();
                file.Load(fileName);
                if (file.DocumentElement == null || file.DocumentElement.Name != "Project")
                {
                    return;
                }

                string attribute = file.DocumentElement.GetAttribute("ToolsVersion");
                if (string.IsNullOrEmpty(attribute))
                {
                    this.Version = 0;
                }
                else if (attribute == "3.5")
                {
                    this.Version = 1;
                }
                else if (attribute == "4.0")
                {
                    this.Version = 2;
                }

                //TODO: High: parse .*proj for targets

                this.Targets = new List<MSBuildFileTarget>(this.DefaultTargets);
            }
            #endregion

            #region vcproj
            else if (extension == ".vcproj")
            {
                XmlDocument file = new XmlDocument();
                file.Load(fileName);
                if (file.DocumentElement == null || file.DocumentElement.Name != "VisualStudioProject")
                {
                    return;
                }

                int slnVersion = int.Parse(file.DocumentElement.GetAttribute("Version"), CultureInfo.InvariantCulture);
                switch (slnVersion)
                {
                    case 11:
                        this.Version = 2;
                        break;
                    case 10:
                        this.Version = 1;
                        break;
                    case 9:
                        this.Version = 0;
                        break;
                }

                //TODO: High: parse .vcproj for targets

                this.Targets = new List<MSBuildFileTarget>(this.DefaultTargets);
            }
            #endregion

            #region proj
            else if ((extension == ".proj") || (extension == ".targets"))
            {
                XmlDocument file = new XmlDocument();
                file.Load(fileName);
                if (file.DocumentElement == null || file.DocumentElement.Name != "Project")
                {
                    return;
                }

                string attribute = file.DocumentElement.GetAttribute("ToolsVersion");
                if (string.IsNullOrEmpty(attribute))
                {
                    this.Version = 0;
                }
                else if (attribute == "3.5")
                {
                    this.Version = 1;
                }
                else if (attribute == "4.0")
                {
                    this.Version = 2;
                }

                this.Targets = new List<MSBuildFileTarget>();

                foreach (XmlNode node in file.DocumentElement.ChildNodes)
                {
                    if (node.Name != "Target")
                    {
                        continue;
                    }

                    XmlAttribute name = node.Attributes["Name"];
                    if (name == null)
                    {
                        continue;
                    }

                    this.Targets.Add(
                        new MSBuildFileTarget()
                        {
                            TargetName = name.Value
                        });
                }
            }
            #endregion

        }

        public string VersionString
        {
            get
            {
                string dotNetVersion = null;

                switch (this.Version)
                {
                    case 0:
                        dotNetVersion = "v2.0.50727";
                        break;
                    case 1:
                        dotNetVersion = "v3.5";
                        break;
                    case 2:
                        dotNetVersion = "v4.0.30319";
                        break;
                }

                return dotNetVersion;
            }
        }
    }
}
